package com.zxd.interview.jmm;


import java.util.concurrent.CountDownLatch;

/**
 * 内存重排序
 */
public class OutOfOrderExecution {

    private static int x = 0, y = 0;
    private static int a = 0, b = 0;

    public static void main(String[] args) throws InterruptedException {
        loadExample();


//        example1();
//        example1();
        example1plus();
    }

    private static void loadExample() {
        int a = 3;
        int b = 2;
        a = a + 1;
    }

    /**
     * 为了更快的出现 example1 的情况，对于程序进行一定升级。
     * @throws InterruptedException
     */
    private static void example1plus() throws InterruptedException {
        int i = 0;

        for (;;){
            i++;
            x = 0;
            y = 0;
            a = 0;
            b = 0;

            CountDownLatch countDownLatch =  new CountDownLatch(1);

            Thread one = new Thread(()->{
                try {
                    countDownLatch.await();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                a = 1;
                x = b;

            });

            Thread two = new Thread(()->{
                try {
                    countDownLatch.await();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                b = 1;
                y = a;

            });

            one.start();
            two.start();
            countDownLatch.countDown();
            one.join();
            two.join();

            String result = "第 " + i + " 次" + "（"+ x + "," + y +"）";
            // 修改下面的部分测试小概率事件
            if(x == 0 && y == 0){
                System.out.println(result);
                break;
            }else{
                System.out.println(result);
            }

        }
    }/**
     if(x == 1 && y == 1) 结果：
     第 241 次（0,1）
     第 242 次（0,1）
     第 243 次（0,1）
     第 244 次（0,1）
     第 245 次（0,1）
     第 246 次（1,1）

     if(x == 0 && y == 0)
     这个条件就是因为JVM或者CPU的重排序导致的。
     第 2519 次（0,1）
     第 2520 次（1,0）
     第 2521 次（0,1）
     */

    /**
     * 第一个例子：重排序的基础问题
     */
    private static void example1() throws InterruptedException {
        Thread one = new Thread(() -> {
           a = 1;
           x = b;
        });

        Thread two = new Thread(() -> {
            b = 1;
            y = a;
        });
        one.start();
        two.start();
        one.join();
        two.join();
        System.err.println("a =" + a);
        System.err.println("b = "+ b);
        System.err.println("x = "+x);
        System.err.println("y =" + y);
    }/**
     运行结果，发现一共有四种情况：
     第一种
     排序结果：x = b;b = 1;a = 1;y=a;
     a = 0，b = 1
     x = 0，y = 1

     第二种
     排序结果：
     b=1;y=a;a=1;x=b
     x = 1，y = 0

     第三种：
     排序结果： a=1，b=1,x=b,y=a
     x=1，y=1

     第四种：（重点，比较难触发）
     排序结果：x=b,y=a,a=1,b=1
     x = 0，y = 0


     重排序指令优化:
     a=3,b=2,a=a+1

     1. load a
     2. set to 3
     3. store a

     1. load b
     2.set to 2
     3. store b

     1. load a
     2. set to 4
     3. store a

     重排序优化：
     a=3,a=a+1,b=2
     => a=4,b=2

     1. load a
     2. set to 3
     3. set to 4
     4. store a

     1. load b
     2.set to 2
     3. store b


     */
}
